// Copyright 2024 Administrator
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { MinioClientService } from "src/core/system/minio/minio.service";
import { DataSource, In, Repository } from "typeorm";
import { Video } from "../entities/video.entity";
import { IVideo } from "../interface/video.interface";

@Injectable()
export class DVideo implements IVideo {


    constructor(
        @InjectRepository(Video) private videoRepository: Repository<Video>,
        private dataSource: DataSource,
        private minioClientService: MinioClientService,
    ) { }


    async findOne(username: string, id: string): Promise<Video> {

        const build = await this.videoRepository
            .createQueryBuilder("video")
            .leftJoinAndSelect("video.artistList", "artist")
            .leftJoinAndSelect("video.song", "song")
            .leftJoinAndSelect('video.genre', "genre")
            .select([
                'video.id',
                'video.title',
                'video.lang',
                'video.objectName',
                'video.introduce',
                'video.poster',
                'video.playnum',
                'video.indexDataAddTime',
                'video.originalReleaseDate',
                'video.createTime',
                'video.duration',
                'video.width',
                'video.height',
                'artist.id',
                'artist.name',
                'song.id',
                'song.title',
                'genre.id',
                'genre.categoryName'
            ]).andWhere("video.id = :id", { id })

        if (username) {
            build.leftJoinAndSelect("video.favoriteUsers", "favor_user", "favor_user.username = :useranme")
                .setParameter('useranme', username)
                .addSelect([
                    'favor_user.id',
                    'favor_user.username',
                ])
        }

        return await build.getOne()
    }
    /**
     * 歌曲-获取分类
     * @param ids 歌曲id列表 
     */
    async getGenresByids(ids: number[]): Promise<number[]> {

        const videoList = await this.videoRepository.find({ where: { "id": In(ids) } })

        let cateList = videoList.flatMap(video => video.genre.map(g => g.id))
        return cateList
    }

    async listBynameOrId(videoName: string, artistIds?: number[]): Promise<Video[]> {
        // return await this.videoRepository.find({ where: { 'title': ILike(`%${videoName}%`)} })
        const build = await this.videoRepository
            .createQueryBuilder("video")
            .leftJoinAndSelect("video.artistList", "artist", "artist.id IN (:...artistIds)")
            .setParameter('artistIds', artistIds)
            .select([
                'video.id',
                'video.title',
                'artist.id',
                'artist.name',
            ])

        if (videoName) {
            build.where('video.title like :keywords', { keywords: `%${videoName}%` });
        }

        const data = await build.getMany();

        return data;
    }

    /**
     * 视频-推荐列表
     * @param username 
     * @param pageNum 
     * @param pageSize 
     */
    async getRecommnedList(username: string, pageNum: number, pageSize: number): Promise<[Video[], number]> {
        const build = await this.videoRepository
            .createQueryBuilder("video")
            .leftJoinAndSelect("video.artistList", "artist")
            .leftJoinAndSelect('video.genre', "genre")
            .select([
                'video.id',
                'video.title',
                'video.lang',
                'video.objectName',
                'video.introduce',
                'video.poster',
                'video.playnum',
                'video.indexDataAddTime',
                'video.originalReleaseDate',
                'video.duration',
                'video.width',
                'video.height',
                'artist.id',
                'artist.name',
                'genre.id',
                'genre.categoryName',
            ])
            .orderBy("video.createTime", 'DESC')
            .offset((pageNum - 1) * pageSize)
            .limit(pageSize)

        if (username) {
            build.leftJoinAndSelect("video.favoriteUsers", "favor_user", "favor_user.username = :useranme")
                .setParameter('useranme', username)
                .addSelect([
                    'favor_user.id',
                    'favor_user.username',
                ])
        }

        const [data, total] = await build.getManyAndCount();
        return [data, total]
    }

    async page(username: string, videoName: string, pageNum: number, pageSize: number): Promise<[Video[], number]> {
        const build = await this.videoRepository
            .createQueryBuilder("video")
            .leftJoinAndSelect("video.artistList", "artist")

            .leftJoinAndSelect('video.genre', "genre")

            .select([
                'video.id',
                'video.title',
                'video.lang',
                'video.objectName',
                'video.introduce',
                'video.poster',
                'video.playnum',
                'video.indexDataAddTime',
                'video.originalReleaseDate',
                'video.duration',
                'video.width',
                'video.height',
                'artist.id',
                'artist.name',
                'genre.id',
                'genre.categoryName'
            ])
            .orderBy("video.createTime", 'DESC')
            .offset((pageNum - 1) * pageSize)
            .limit(pageSize)

        if (videoName) {
            build.where('video.title like :keywords', { keywords: `%${videoName}%` });
        }

        if (username) {
            build.leftJoinAndSelect("video.favoriteUsers", "favor_user", "favor_user.username = :useranme")
                .setParameter('useranme', username)
                .addSelect([
                    'favor_user.id',
                    'favor_user.username',
                ])
        }

        const [data, total] = await build.getManyAndCount();
        return [data, total]
    }

}